package com.lantosec.hmrp.modules.sysdata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lantosec.hmrp.core.kit.PageVO;
import com.lantosec.hmrp.core.util.UUIDUtils;
import com.lantosec.hmrp.modules.sysdata.entity.SysDataProcess;
import com.lantosec.hmrp.modules.sysdata.mapper.SysDataProcessMapper;
import com.lantosec.hmrp.modules.sysdata.service.ISysDataProcessService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lantosec.hmrp.modules.sysdata.vo.ProcessInstanceStatisticsVO;
import com.lantosec.hmrp.modules.system.entity.SysUser;
import com.lantosec.hmrp.modules.system.service.ISysUserService;
import com.lantosec.hmrp.modules.workflow.enumeration.ProcessStatusEnum;
import com.lantosec.hmrp.modules.workflow.vo.SysDataProcessQueryVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.context.annotation.Primary;
import lombok.extern.log4j.Log4j2;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统数据流程关联表 服务实现类
 * </p>
 *
 * @author AutoCode
 * @since 2020-05-22
 */
@Service
@Primary
@Log4j2
public class SysDataProcessServiceImpl extends ServiceImpl<SysDataProcessMapper, SysDataProcess> implements ISysDataProcessService {

    @Autowired
    ISysUserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveProcess(String formTableId, String proInsId, String proInsName, String dataId, String currentTaskId) {
        SysDataProcess dbDataProcess = baseMapper.selectOne(new QueryWrapper<SysDataProcess>()
                .eq(String.valueOf(SysDataProcess.ColName.pro_ins_id), proInsId));
        Date now = new Date();
        if (Objects.isNull(dbDataProcess)) {
            SysDataProcess dataProcess = new SysDataProcess();
            dataProcess.setDataProcessId(UUIDUtils.get());
            dataProcess.setProInsId(proInsId);
            dataProcess.setProInsName(proInsName);
            dataProcess.setFormTableId(formTableId);
            dataProcess.setDataId(dataId);
            // TODO 数据库数据对应的数据表,暂时未实现,需要一张表维护流程表单数据与发起流程的数据表的关系,然后从这张表查询
            dataProcess.setDataSourceTableSchema("");
            dataProcess.setDataSourceTableName("");
            dataProcess.setCurrentTaskId(currentTaskId);
            dataProcess.setCreateTime(now);
            int flag = baseMapper.insert(dataProcess);
            if (flag > 0) {
                return true;
            }
        } else {
            dbDataProcess.setProInsId(proInsId);
            dbDataProcess.setFinishTime(now);
            int flag = baseMapper.updateById(dbDataProcess);
            if (flag > 0) {
                return true;
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertProcess(String formTableId, String processDefinitionId, String deploymentId, String proInsId, String proInsName
            , String dataId, String currentTaskId, String currentTaskKey, String currentTaskName, String startUserId, String processTypeId) {
        SysDataProcess dataProcess = new SysDataProcess();
        dataProcess.setDataProcessId(UUIDUtils.get());
        dataProcess.setProcessDefinitionId(processDefinitionId);
        dataProcess.setProcessDeploymentId(deploymentId);
        dataProcess.setProInsId(proInsId);
        dataProcess.setProInsName(proInsName);
        dataProcess.setFormTableId(formTableId);
        dataProcess.setDataId(dataId);
        // TODO 数据库数据对应的数据表,暂时未实现,需要一张表维护流程表单数据与发起流程的数据表的关系,然后从这张表查询
        dataProcess.setDataSourceTableSchema("");
        dataProcess.setDataSourceTableName("");
        dataProcess.setStartUserId(startUserId);
        dataProcess.setCurrentTaskId(currentTaskId);
        dataProcess.setCurrentTaskKey(currentTaskKey);
        dataProcess.setCurrentTaskName(currentTaskName);
        dataProcess.setCreateTime(new Date());
        dataProcess.setProcessStatus(ProcessStatusEnum.PROCESSING.getType());
        dataProcess.setProcessTypeId(processTypeId);
        int flag = baseMapper.insert(dataProcess);
        if (flag > 0) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateProcess(String proInsId, String currentTaskId, String currentTaskKey, String currentTaskName
            , Date finishTime, String processStatus, String formTableId) {
        SysDataProcess dataProcess = new SysDataProcess();
        //.setProInsId(proInsId);
        if (StringUtils.isNotEmpty(currentTaskId)) {
            dataProcess.setCurrentTaskId(currentTaskId);
        }
        if (StringUtils.isNotEmpty(currentTaskKey)) {
            dataProcess.setCurrentTaskKey(currentTaskKey);
        }
        if (StringUtils.isNotEmpty(currentTaskName)) {
            dataProcess.setCurrentTaskName(currentTaskName);
        }
        if (!Objects.isNull(finishTime)) {
            dataProcess.setFinishTime(finishTime);
        }
        if (StringUtils.isNotEmpty(processStatus)) {
            dataProcess.setProcessStatus(processStatus);
        }
        if (StringUtils.isNotEmpty(processStatus)) {
            dataProcess.setFormTableId(formTableId);
        }
        int flag = baseMapper.update(dataProcess, new QueryWrapper<SysDataProcess>()
                .eq(String.valueOf(SysDataProcess.ColName.pro_ins_id), proInsId));
        if (flag > 0) {
            return true;
        }

        return false;
    }

    @Override
    public Page<SysDataProcess> selectByStartUserId(PageVO page, String userId) {
        Page<SysDataProcess> p = baseMapper.selectPage(page, new QueryWrapper<SysDataProcess>()
                .eq(StringUtils.isNotEmpty(userId), String.valueOf(SysDataProcess.ColName.start_user_id), userId)
                .orderByDesc(String.valueOf(SysDataProcess.ColName.create_time)));
        return p;
    }

    @Override
    public List<SysDataProcess> selectByStartUserId(String userId){
        List<SysDataProcess> list = baseMapper.selectList(new QueryWrapper<SysDataProcess>()
                .eq(StringUtils.isNotEmpty(userId),String.valueOf(SysDataProcess.ColName.start_user_id),userId)
                .orderByDesc(String.valueOf(SysDataProcess.ColName.create_time)));
        return list;
    }

    @Override
    public long countStartProcess(String userId) {
        return baseMapper.selectCount(new QueryWrapper<SysDataProcess>()
                .eq(StringUtils.isNotEmpty(userId), String.valueOf(SysDataProcess.ColName.start_user_id), userId));
    }

    @Override
    public long queryProcessInstanceCount(SysDataProcessQueryVO condition) {
        return baseMapper.selectCount(getSearch(condition));
    }

    private QueryWrapper<SysDataProcess> getSearch(SysDataProcessQueryVO condition) {
        List<String> userIdList = new ArrayList<>();
        if (StringUtils.isNotEmpty(condition.getStartUserName())) {
            List<SysUser> userList = userService.getBaseMapper()
                    .selectList(new QueryWrapper<SysUser>().like(String.valueOf(SysUser.ColName.name), condition.getStartUserName()));
            userIdList = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(userIdList)) {
                userIdList.add("");
            }
        }
        return new QueryWrapper<SysDataProcess>()
                .eq(StringUtils.isNotEmpty(condition.getProcessTypeId()), String.valueOf(SysDataProcess.ColName.process_type_id), condition.getProcessTypeId())
                .eq(StringUtils.isNotEmpty(condition.getProcessStatus()), String.valueOf(SysDataProcess.ColName.process_status), condition.getProcessStatus())
                .in(StringUtils.isNotEmpty(condition.getStartUserName()), String.valueOf(SysDataProcess.ColName.start_user_id), userIdList)
                .like(StringUtils.isNotEmpty(condition.getProInsName()), String.valueOf(SysDataProcess.ColName.pro_ins_name), condition.getProInsName())
                .ge(StringUtils.isNotEmpty(condition.getStartTime()), String.valueOf(SysDataProcess.ColName.create_time), condition.getStartTime())
                .le(StringUtils.isNotEmpty(condition.getEndTime()), String.valueOf(SysDataProcess.ColName.create_time), condition.getEndTime());
    }

    @Override
    public Page<SysDataProcess> queryProcessInstanceList(PageVO<SysDataProcess> page, SysDataProcessQueryVO condition) {
        PageVO<SysDataProcess> list = baseMapper.selectPage(page, getSearch(condition).orderByDesc(String.valueOf(SysDataProcess.ColName.create_time)));
        if (CollectionUtils.isNotEmpty(list.getRecords())) {
            List<String> startUserIdList = list.getRecords().stream().map(SysDataProcess::getStartUserId).collect(Collectors.toList());
            List<SysUser> userList = userService.getBaseMapper()
                    .selectList(new QueryWrapper<SysUser>().in(String.valueOf(SysUser.ColName.user_id), startUserIdList));

            list.getRecords().forEach(it -> {
                String name = userList.stream().filter(a -> a.getUserId().equals(it.getStartUserId())).findFirst()
                        .orElse(new SysUser()).getName();
                it.setUserName(name);
            });
        }

        return page.setRecords(list.getRecords());
    }

    @Override
    public List<ProcessInstanceStatisticsVO> queryProcessInstanceStatistics(String startTime, String endTime) {
        return baseMapper.queryProcessInstanceStatistics(startTime, endTime);
    }

    @Override
    public int deleteByDeploymentId(String deploymentId) {
        return baseMapper.delete(new QueryWrapper<SysDataProcess>()
                .eq(String.valueOf(SysDataProcess.ColName.process_deployment_id), deploymentId));
    }
}
